package control;

import java.io.Serializable;
import java.util.Date;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.inject.Inject;
import javax.inject.Named;

import service.ProjetoService;
import service.RecursoService;
import service.RequisitoService;

import entity.Atividade;
import entity.CasoUso;
import entity.Disciplina;
import entity.Iteracao;
import entity.Periodo;
import entity.Recurso;
import entity.Requisito;

@Named
@SessionScoped
public class PlanejarIteracaoControl implements Serializable {
	private static final long serialVersionUID = -5739906867149200370L;
	private Long idIteracao;
	private Iteracao iteracao;
	private List<Atividade> atividades;
	private List<Recurso> recursos;
	private String outrosRecursos;
	
	private Disciplina[] disciplinas  = Disciplina.values();
	
	private Atividade atividade;
	private Date inicioAtividade;
	private Date fimAtividade;
	
	private Long idAtividadeSel;
	private Integer idRecursoSel;
	private Long idRequisitoSel;
	private Long idPredecessoraSel;
	private Integer idCasoUsoSel;
	
	private List<Recurso> recursosNaoVinculados;
	
	private List<Requisito> requisitosNaoVinculadosAIteracao;
	private List<Requisito> requisitosDaIteracao;
	private List<Requisito> requisitosNaoVinculadosAAtividade;
	private List<Requisito> requisitosDaAtividade;
	
	private List<CasoUso> casosUsoNaoVinculadosAIteracao;
	private List<CasoUso> casosUsoDaIteracao;
	private List<CasoUso> casosUsoNaoVinculadosAAtividade;
	private List<CasoUso> casosUsoDaAtividade;
	
	private List<Atividade> atividadesPredecessoras;
	private List<Atividade> atividadesNaoVinculadas;
	
	@Inject
	private MenuControl menu;
	
	@Inject
	private AcompanharProjetoControl acompanharProjetoControl;
	
	@EJB
	private ProjetoService projetoService;
	
	@EJB
	private RecursoService recursoService;
	
	@EJB
	private RequisitoService requisitoService;
	
	public String iniciar() {
		iteracao = projetoService.planejarIteracao(idIteracao);			
		
		return carregarPgInicial();
	}
	
	public String planejarProximaIteracao() {
		iteracao = projetoService.planejarProximaIteracao(menu.getIdProjetoSelecionado());
		idIteracao = iteracao.getId();
		
		return carregarPgInicial();
	}
	

	public String carregarPgInicial() {
		atividades = projetoService.listarAtividadesDaIteracao(iteracao.getId());
		recursos = recursoService.listarRecursosDaIteracao(iteracao.getId());
		requisitosDaIteracao = requisitoService.listarRequisitosDaIteracao(iteracao.getId());
		outrosRecursos = iteracao.getOutrosRecursos();
		casosUsoDaIteracao = requisitoService.listarCasosUsoDaIteracao(idIteracao);
		
		return "/pages/projeto/planejar_iteracao.xhtml";
	}
	
	public String replanejar() {
		iteracao = projetoService.replanejarIteracao(idIteracao);
		return carregarPgInicial();
	}
	
	public String novaAtividade() {
		projetoService.criarAtividadeNaIteracao(iteracao.getId());
		atividades = projetoService.listarAtividadesDaIteracao(iteracao.getId());
		
		return "";
	}
	
	public String removerAtividade() {
		projetoService.removerAtividade(idAtividadeSel);
		atividades = projetoService.listarAtividadesDaIteracao(iteracao.getId());
		iteracao = projetoService.obterIteracaoComAtividadesERecursos(idIteracao);
		
		return "";
	}
	
	public String editarAtividade() {
		atividade = projetoService.obterAtividadeCompleta(idAtividadeSel);
		inicioAtividade = atividade.getInicioEstimado();
		fimAtividade = atividade.getFimEstimado();
		idRecursoSel = atividade.getResponsavel() != null ? atividade.getResponsavel().getIdRecurso() : null;
		
		return "";
	}
	
	public String salvarAtividade() {
		atividade.setPeriodo(new Periodo(inicioAtividade, fimAtividade));
		projetoService.alterarAtividade(atividade);
		atividades = projetoService.listarAtividadesDaIteracao(iteracao.getId());
		iteracao = projetoService.obterIteracaoComAtividadesERecursos(idIteracao);
		
		return "";
	}
	
	public String listarRecursos() {
		recursosNaoVinculados = recursoService.listarRecursosNaoVinculadosAIteracao(iteracao.getId());
		
		return "";
	}
	
	public String adicionarRecurso() {
		projetoService.adicionarRecursoAIteracao(iteracao.getId(), idRecursoSel);
		recursos = recursoService.listarRecursosDaIteracao(iteracao.getId());
		
		return "";
	}
	
	public String removerRecurso() {
		projetoService.removerRecursoDaIteracao(iteracao.getId(), idRecursoSel);
		recursos = recursoService.listarRecursosDaIteracao(iteracao.getId());
		
		return "";
	}
	
	public String listarRequisitosNaoVinculados() {
		requisitosNaoVinculadosAIteracao = requisitoService.listarRequisitosNaoVinculadosAIteracao(iteracao.getId());
		
		return "";
	}
	
	public String adicionarRequisitoAIteracao() {
		projetoService.adicionarRequisitoAIteracao(idRequisitoSel, iteracao.getId());
		requisitosDaIteracao = requisitoService.listarRequisitosDaIteracao(iteracao.getId());
		
		return "";
	}
	
	public String listarRequisitosDaAtividade() {
		idRequisitoSel = null;
		atividade = projetoService.obterAtividadeCompleta(idAtividadeSel);
		requisitosNaoVinculadosAAtividade = requisitoService.listarRequisitosNaoVinculadosAAtividade(idAtividadeSel);
		requisitosDaAtividade = new ArrayList<Requisito>(atividade.getRequisitos());
		
		Collections.sort(requisitosDaAtividade, new Comparator<Requisito>() {
			@Override
			public int compare(Requisito r1, Requisito r2) {
				return r1.getId().compareTo(r2.getId());
			}
		});
		
		casosUsoNaoVinculadosAAtividade = requisitoService.listarCasosUsoNaoVinculadosAAtividade(idAtividadeSel);
		casosUsoDaAtividade = requisitoService.listarCasosUsoDaAtividade(idAtividadeSel);
		
		return "";
	}
	
	public String adicionarRequisitosAAtividade() {
		if (idRequisitoSel != null) {
			projetoService.adicionarRequisitoAAtividade(idRequisitoSel, idAtividadeSel);
		}
		return listarRequisitosDaAtividade();
	}
	
	public String removerRequisitoDaIteracao() {
		projetoService.removerRequisitoDaIteracao(idRequisitoSel, iteracao.getId());
		requisitosDaIteracao = requisitoService.listarRequisitosDaIteracao(iteracao.getId());
		
		return "";
	}
	
	public String removerRequisitoDaAtividade() {
		projetoService.removerRequisitoDaAtividade(idRequisitoSel, idAtividadeSel);
		
		return listarRequisitosDaAtividade();
	}
	
	public String listarAtividadesPredecessoras() {
		atividade = projetoService.obterAtividadeComPredecessoras(idAtividadeSel);
		atividadesNaoVinculadas = projetoService.listarAtividadesDaIteracaoNaoVinculadasA(idAtividadeSel);
		
		atividadesPredecessoras = new ArrayList<Atividade>(atividade.getAtividadesPredecessoras());
		Collections.sort(atividadesPredecessoras, new Comparator<Atividade>() {
			@Override
			public int compare(Atividade a1, Atividade a2) {
				return a1.getNumero().compareTo(a2.getNumero());
			}
		});
		
		return "";
	}
	
	public String adicionarAtividadePredecessora() {
		projetoService.adicionarAtividadePredecessora(idAtividadeSel, idPredecessoraSel);
		atividades = projetoService.listarAtividadesDaIteracao(iteracao.getId());
		
		return listarAtividadesPredecessoras();
	}
	
	public String removerAtividadePredecessora() {
		projetoService.removerAtividadePredecessora(idAtividadeSel, idPredecessoraSel);
		
		return listarAtividadesPredecessoras();
	}
	
	public void selecionarRecurso(ValueChangeEvent e) {
		Integer idRecurso = (Integer) e.getNewValue();
		for (Recurso r : recursos) {
			if (r.getIdRecurso().equals(idRecurso)) {
				atividade.setResponsavel(r);
				break;
			}
		}
	}
	
	public String concluirPlanejamento() {
		projetoService.concluirPlanejamentoIteracao(iteracao.getId());
		
		acompanharProjetoControl.setIdIteracaoSelecionada(iteracao.getId());
		return acompanharProjetoControl.visualizarIteracao();
	}
	
	public String salvarOutrosRecursos() {
		projetoService.salvarOutrosRecursosIteracao(idIteracao, outrosRecursos);
		
		FacesContext.getCurrentInstance().addMessage(null, 
				new FacesMessage(FacesMessage.SEVERITY_INFO, "'Outros recursos' salvos com sucesso.", ""));
		
		return "";
	}
	
	// Casos de Uso
	public String listarCasosUsoNaoVinculados() {
		casosUsoNaoVinculadosAIteracao = requisitoService.listarCasosUsoNaoVinculadosAIteracao(idIteracao);
		return "";
	}

	public String adicionarCasoUsoAIteracao() {
		projetoService.adicionarCasoUsoAIteracao(idCasoUsoSel, idIteracao);
		casosUsoDaIteracao = requisitoService.listarCasosUsoDaIteracao(idIteracao);
		requisitosDaIteracao = requisitoService.listarRequisitosDaIteracao(iteracao.getId());
		
		return "";
	}
	
	public String removerCasoUsoDaIteracao() {
		projetoService.removerCasoUsoDaIteracao(idCasoUsoSel, idIteracao);
		casosUsoDaIteracao = requisitoService.listarCasosUsoDaIteracao(idIteracao);
		
		return "";
	}
	
	public String adicionarCasoUsoAAtividade() {
		projetoService.adicionarCasoUsoAAtividade(idCasoUsoSel, idAtividadeSel);
		
		return listarRequisitosDaAtividade();
	}
	
	public String removerCasoUsoDaAtividade() {
		projetoService.removerCasoUsoDaAtividade(idCasoUsoSel, idAtividadeSel);
		
		return listarRequisitosDaAtividade();
	}
	
	
	public Iteracao getIteracao() {
		return iteracao;
	}

	public Atividade getAtividade() {
		return atividade;
	}

	public void setAtividade(Atividade atividadeSel) {
		this.atividade = atividadeSel;
	}

	public Long getIdAtividadeSel() {
		return idAtividadeSel;
	}

	public void setIdAtividadeSel(Long numAtividadeSel) {
		this.idAtividadeSel = numAtividadeSel;
	}

	public Disciplina[] getDisciplinas() {
		return disciplinas;
	}

	public Integer getIdRecursoSel() {
		return idRecursoSel;
	}

	public void setIdRecursoSel(Integer idRecursoSel) {
		this.idRecursoSel = idRecursoSel;
	}

	public List<Recurso> getRecursosNaoVinculados() {
		return recursosNaoVinculados;
	}

	public List<Atividade> getAtividades() {
		return atividades;
	}

	public List<Recurso> getRecursos() {
		return recursos;
	}

	public List<Requisito> getRequisitosDaIteracao() {
		return requisitosDaIteracao;
	}

	public void setRequisitosDaIteracao(List<Requisito> requisitosDaIteracao) {
		this.requisitosDaIteracao = requisitosDaIteracao;
	}

	public List<Requisito> getRequisitosDaAtividade() {
		return requisitosDaAtividade;
	}

	public void setRequisitosDaAtividade(List<Requisito> requisitosDaAtividade) {
		this.requisitosDaAtividade = requisitosDaAtividade;
	}

	public Long getIdRequisitoSel() {
		return idRequisitoSel;
	}

	public void setIdRequisitoSel(Long idRequisitoSel) {
		this.idRequisitoSel = idRequisitoSel;
	}

	public List<Requisito> getRequisitosNaoVinculadosAIteracao() {
		return requisitosNaoVinculadosAIteracao;
	}

	public List<Requisito> getRequisitosNaoVinculadosAAtividade() {
		return requisitosNaoVinculadosAAtividade;
	}

	public List<Atividade> getAtividadesPredecessoras() {
		return atividadesPredecessoras;
	}

	public List<Atividade> getAtividadesNaoVinculadas() {
		return atividadesNaoVinculadas;
	}

	public Long getIdPredecessoraSel() {
		return idPredecessoraSel;
	}

	public void setIdPredecessoraSel(Long idPredecessoraSel) {
		this.idPredecessoraSel = idPredecessoraSel;
	}

	public Date getInicioAtividade() {
		return inicioAtividade;
	}

	public void setInicioAtividade(Date inicioAtividade) {
		this.inicioAtividade = inicioAtividade;
	}

	public Date getFimAtividade() {
		return fimAtividade;
	}

	public void setFimAtividade(Date fimAtividade) {
		this.fimAtividade = fimAtividade;
	}

	public Long getIdIteracao() {
		return idIteracao;
	}

	public void setIdIteracao(Long idIteracao) {
		this.idIteracao = idIteracao;
	}

	public String getOutrosRecursos() {
		return outrosRecursos;
	}

	public void setOutrosRecursos(String outrosRecursos) {
		this.outrosRecursos = outrosRecursos;
	}

	public List<CasoUso> getCasosUsoNaoVinculadosAIteracao() {
		return casosUsoNaoVinculadosAIteracao;
	}

	public List<CasoUso> getCasosUsoDaIteracao() {
		return casosUsoDaIteracao;
	}

	public Integer getIdCasoUsoSel() {
		return idCasoUsoSel;
	}

	public void setIdCasoUsoSel(Integer idCasoUsoSel) {
		this.idCasoUsoSel = idCasoUsoSel;
	}

	public List<CasoUso> getCasosUsoNaoVinculadosAAtividade() {
		return casosUsoNaoVinculadosAAtividade;
	}

	public List<CasoUso> getCasosUsoDaAtividade() {
		return casosUsoDaAtividade;
	}
}
